package com.ifcar.app.view;

import android.content.Context;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.Transformation;
import android.widget.Gallery;

/**
 * fling 只滑动一屏的Gallery.<br/>
 * 
 * @author wjying
 */
public class MyGallery extends Gallery {
	private int mAutoTimeInterval;

	private Runnable mXXXRunnable;

	private boolean mFirstScroll;

	private int mLastMotionX;
	private int mTouchSlop;
	
	private boolean mInLayout;
	/**
	 * 自动滑动切换Runnable.
	 */
	private Runnable mAutoRunnable = new Runnable() {
		@Override
		public void run() {
			scrollRight();
			if (mAutoTimeInterval > 0) {
				postDelayed(this, mAutoTimeInterval);
			}
		}
	};

	public MyGallery(Context context) {
		super(context);
		init(context);
	}

	public MyGallery(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init(context);
	}

	public MyGallery(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}

	private void init(Context context) {
		setSpacing(0);
		setUnselectedAlpha(1.f);
		setSoundEffectsEnabled(false);
		setFadingEdgeLength(0);

		final ViewConfiguration configuration = ViewConfiguration.get(context);
		mTouchSlop = configuration.getScaledTouchSlop();
	}

	public void setAutoRun(int interval) {
		mAutoTimeInterval = interval;
		if (interval > 0) {
			setAnimationDuration(1000);
			startAutoScroll(true);
		} else {
			startAutoScroll(false);
		}

	}
	
	@Override
	protected void onLayout(boolean changed, int left, int top, int right,
			int bottom) {
		mInLayout = true;
		super.onLayout(changed, left, top, right, bottom);
		mInLayout = false;
	}
	
	public boolean inLayout() {
		return mInLayout;
	}

	@Override
	public void computeScroll() {
		super.computeScroll();
		final Runnable r = mXXXRunnable;
		if (r != null) {
			if (getSelectedView() == null) {
				mXXXRunnable = null;
			} else if (getCenterOfGallery() == getCenterOfView(getSelectedView())) {
				mXXXRunnable = null;
				post(r);
			}

		}

	}

	public void setXXXRunnalbe(Runnable r) {
		if (mXXXRunnable != null) {
			removeCallbacks(mXXXRunnable);
		}
		mXXXRunnable = r;
		invalidate();
	}

	/**
	 * @return The center of this Gallery.
	 */
	private int getCenterOfGallery() {
		return (getWidth() - getPaddingLeft() - getPaddingRight()) / 2
				+ getPaddingLeft();
	}

	/**
	 * @return The center of the given view.
	 */
	private static int getCenterOfView(View view) {
		return view.getLeft() + view.getWidth() / 2;
	}

	@Override
	protected boolean getChildStaticTransformation(View child, Transformation t) {
		return false;
	}

	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		int action = ev.getAction();
		switch (action) {
		case MotionEvent.ACTION_DOWN:
			mFirstScroll = true;
			mLastMotionX = (int) ev.getX();
			super.onTouchEvent(ev);
			break;
		case MotionEvent.ACTION_MOVE:
			final int deltaX = (int) ev.getX() - mLastMotionX;
			if (Math.abs(deltaX) > mTouchSlop) {
				return true;
			}
			break;

		default:
			break;
		}
		return super.onInterceptTouchEvent(ev);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		startAutoScroll(true);
		
		int action = event.getAction();
		if (action != MotionEvent.ACTION_DOWN) {
			super.onTouchEvent(event);
		} 

		if (action == MotionEvent.ACTION_UP) {
			dispatchUnpress();
		} else if (action == MotionEvent.ACTION_CANCEL) {
			dispatchUnpress();
		}

		return true;
	}

	@Override
	public boolean onDown(MotionEvent e) {
		boolean ret = super.onDown(e);
		dispatchUnpress();
		return ret;
	}

	@Override
	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
			float distanceY) {
		boolean ret = super.onScroll(e1, e2, distanceX, distanceY);
		if (mFirstScroll) {
			mFirstScroll = false;
			dispatchUnpress();
		}

		return ret;
	}

	@Override
	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
			float velocityY) {
		if (e2.getX() > e1.getX()) {
			scrollLeft();
		} else {
			scrollRight();
		}
		return true;
	}

	@Override
	public void onShowPress(MotionEvent e) {
		super.onShowPress(e);
		if (getOnItemClickListener() != null) {
			dispatchPress();
		}
	}

	@Override
	public void onLongPress(MotionEvent e) {
		if (getOnItemLongClickListener() != null) {
			super.onLongPress(e);
		}
	}

	private void dispatchUnpress() {
		setPressed(false);
		for (int i = getChildCount() - 1; i >= 0; i--) {
			getChildAt(i).setPressed(false);
		}
	}

	private void dispatchPress() {
		setPressed(true);
	}

	private void scrollLeft() {
		onKeyDown(KeyEvent.KEYCODE_DPAD_LEFT, null);
	}

	private void scrollRight() {
		onKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, null);
	}

	@Override
	protected void onWindowVisibilityChanged(int visibility) {
		super.onWindowVisibilityChanged(visibility);
		if (visibility == VISIBLE && isShown()) {
			startAutoScroll(true);
		} else {
			startAutoScroll(false);
		}
	}

	@Override
	protected void onDetachedFromWindow() {
		super.onDetachedFromWindow();
		startAutoScroll(false);
	}

	public void startAutoScroll(boolean autoScroll) {
		removeCallbacks(mAutoRunnable);
		if (autoScroll && mAutoTimeInterval > 0) {
			postDelayed(mAutoRunnable, mAutoTimeInterval);
		}
	}

}
